package cn.schoolwow.quickdao.module.database.dml.instance.flow.insert.common;

import cn.schoolwow.quickdao.annotation.IdStrategy;
import cn.schoolwow.quickdao.domain.QuickDAOConfig;
import cn.schoolwow.quickdao.domain.entity.Property;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.dto.FlowContextDataRange;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.query.instance.QueryInstance;
import cn.schoolwow.util.domain.query.reflection.QueryReflection;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class SetInsertInstanceParameterFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        QuickDAOConfig quickDAOConfig = flowContext.checkInstanceData(QuickDAOConfig.class);
        Object instance = flowContext.checkData("instance");
        List<Property> propertyList = (List<Property>) flowContext.checkData("propertyList");

        List<Object> parameters = new ArrayList();
        for (Property property : propertyList) {
            if (property.id && property.strategy == IdStrategy.AutoIncrement) {
                continue;
            }
            if (property.id && property.strategy == IdStrategy.IdGenerator) {
                flowContext.putTemporaryData("idProperty", property);
                setNextGenerateId(flowContext);
            }
            if (property.createdAt||property.updateAt) {
                flowContext.startFlow(new SetCurrentDateTimeFlow())
                        .putInstanceData(property, FlowContextDataRange.CurrentCompositeBusiness)
                        .execute();
            }
            Object value = null;
            if (null != quickDAOConfig.databaseOption.insertColumnValueFunction) {
                value = quickDAOConfig.databaseOption.insertColumnValueFunction.apply(property);
            }
            if (null == value) {
                value = QueryInstance.newQuery(instance)
                        .execute()
                        .getSingleFieldValue(property.name);
            }
            parameters.add(value);
        }
        flowContext.putTemporaryData("parameters", parameters);
    }

    @Override
    public String name() {
        return "设置插入实例参数列表";
    }

    private void setNextGenerateId(FlowContext flowContext){
        QuickDAOConfig quickDAOConfig = flowContext.checkInstanceData(QuickDAOConfig.class);
        Property idProperty = (Property) flowContext.checkData("idProperty");
        Object instance = flowContext.checkData("instance");

        Field idField = QueryReflection.newQuery(instance.getClass())
                .execute()
                .getField(idProperty.name);
        String value = quickDAOConfig.databaseOption.idGenerator.getNextId();
        try {
            switch (idField.getType().getName()) {
                case "int": {
                    idField.setInt(instance, Integer.parseInt(value));
                }
                break;
                case "java.lang.Integer": {
                    idField.set(instance, Integer.parseInt(value));
                }
                break;
                case "long": {
                    idField.setLong(instance, Long.parseLong(value));
                }
                break;
                case "java.lang.Long": {
                    idField.set(instance, Long.parseLong(value));
                }
                break;
                case "java.lang.String": {
                    idField.set(instance, value);
                }
                break;
                default: {
                    throw new IllegalArgumentException("当前仅支持int,long,String类型的自增主键!自增字段名称:" + idField.getName() + ",类型:" + idField.getType().getName() + "!");
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("设置自增字段值时发生异常", e);
        }
    }
}
